package com.zis.gateway.filer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import com.zis.gateway.client.VerifyClient;
import com.zis.starter.core.ResponseEntity;
import com.zis.starter.redis.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Date;

/**
 * Create by wangshen 2018/3/27
 */
@Component
public class TokenFilter extends ZuulFilter {

    private static Logger logger = LoggerFactory.getLogger(TokenFilter.class);

    @Autowired
    private VerifyClient verifyClient;

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String uri = request.getRequestURI();
        if(uri.equals("/api/auth/login")) {
            return false;
        }
        if(uri.contains("/api/wechat/web")) {
            return false;
        }
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        try {
            HttpServletRequest request = ctx.getRequest();
            String token = "";//request.getHeader("x-access-token");
            Cookie[] cookies = request.getCookies();
            for (Cookie cookie : cookies) {
                switch(cookie.getName()){
                    case "token":
                        token = cookie.getValue();
                        break;
                    default:
                        break;
                }
            }
            if (token == null || token.equals("")) {
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(401);
                ctx.setResponseBody(JSON.toJSONString(ResponseEntity.failure("token is not exists.")));
            }
            // 验证token合法性
            ResponseEntity respEntity = verifyClient.tokenVerify(token);
            if (respEntity.getCode() != 0) {
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(401);
                ctx.setResponseBody(JSON.toJSONString(ResponseEntity.failure("No authorized request.")));
            } else {
                //传递auth_code
                JSONObject claims = JSON.parseObject(JSON.toJSONString(respEntity.getRespData()));
                InputStream in = ctx.getRequest().getInputStream();
                String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
                JSONObject jsonObj = null;
                if (!body.equals("")) {
                    jsonObj = JSON.parseObject(body);
                    if (jsonObj.containsKey("params")) {
                        JSONObject paramsJSON = jsonObj.getJSONObject("params");
                        paramsJSON.put("authCode", claims.getString("authCode"));
                        jsonObj.put("params", paramsJSON);
                    } else {
                        jsonObj.put("authCode", claims.getString("authCode"));
                    }
                    String uri = request.getRequestURI();
                    if(uri.contains("save")){
                        jsonObj.put("createUser", claims.getString("userId"));
                        jsonObj.put("createDate", new Date());
                    }
                    if(uri.contains("update")){
                        jsonObj.put("updateUser", claims.getString("userId"));
                        jsonObj.put("updateDate", new Date());
                    }
                    String newBody = jsonObj.toString();
                    final byte[] reqBodyBytes = newBody.getBytes();
                    ctx.setRequest(new HttpServletRequestWrapper(request) {
                        @Override
                        public ServletInputStream getInputStream() throws IOException {
                            return new ServletInputStreamWrapper(reqBodyBytes);
                        }
                        @Override
                        public int getContentLength() {
                            return reqBodyBytes.length;
                        }
                        @Override
                        public long getContentLengthLong() {
                            return reqBodyBytes.length;
                        }
                    });
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            ctx.set("error.status_code", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            ctx.set("error.exception", e);
        }
        return null;
    }

}
